import base64

import pickle
from django.shortcuts import render

# Create your views here.
from django_redis import get_redis_connection
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView

from carts.serializers import CartSerializer, CartSKUSerializer, CartDeleteSerializer
from goods.models import SKU


class CartView(APIView):
    # 不去校验token
    def perform_authentication(self, request):
        pass

    """购物车添加数据"""

    def post(self, request):
        """
        1.创建序列化器,对数据进行校验
        2.获取sku_id,count,selected
        3.判断用户是否登陆
        4.登陆用户将数据保存在redis
        5.未登录用户将数据保存在cookie
         #获取cookie的数据,查看商品是否已经存在,存在修改,不存在添加
        6.返回响应
        """

        # 1.创建序列化器,对数据进行校验
        serializer = CartSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 2.获取sku_id,count,selected
        sku_id = serializer.data.get('sku_id')
        count = serializer.data.get('count')
        selected = serializer.data.get('selected')
        # 3.判断用户是否登陆
        try:
            user = request.user
        except:
            user = None
        # 4.登陆用户将数据保存在redis
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('cart')
            # 创建管道对象(减少对redis的连接)
            p1 = redis_conn.pipeline()
            # redis哈希数据保存hincrby
            p1.hincrby('cart_%s' % user.id, sku_id, count)
            # 校验是否勾选
            if selected:
                # redis集合保存数据sadd
                p1.sadd('cart_selected_%s' % user.id, sku_id)
            # 执行管道命令
            p1.execute()
            return Response(serializer.data)
        # 5.未登录用户将数据保存在cookie
        #  #获取cookie的数据,查看商品是否已经存在
        else:
            cart_str = request.COOKIES.get('cart')
            if cart_str is not None:
                # cookie里有数据,解码数据
                cart_bytes = base64.b64decode(cart_str)
                cart = pickle.loads(cart_bytes)
            else:
                cart = {}

            # 更新购物车(商品存在更新数量,不存在即添加)
            if sku_id in cart:  # cart = {sku_id:{'count':xxx,'selected':xxxx},...}
                origin_count = cart[sku_id]['count']
                count += origin_count

            cart[sku_id] = {
                'count': count,
                'selected': selected
            }
            # 将购物车信息编码保存在cookie
            # 编码
            cart_byte = pickle.dumps(cart)
            cart_cookie = base64.b64encode(cart_byte).decode()
            # 保存
            response = Response(serializer.data)
            response.set_cookie('cart', cart_cookie)

            # 6.返回响应
            return response

    """查看购物车"""

    def get(self, requset):
        """
        1.校验用户是否登陆
        2.登陆用户redis查询数据
        3.未登录用户cookie查询
        4.查询商品对象,并查询到商品的count和selected
        5.将商品信息序列化,返回
        """
        # 1.校验用户是否登陆
        try:
            user = requset.user
        except:
            user = None
        # 2.登陆用户redis查询数据
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('cart')
            # 创建管道对象
            # p1 = redis_conn.pipeline()
            redis_cart = redis_conn.hgetall('cart_%s' % user.id)
            redis_selected = redis_conn.smembers('cart_selected_%s' % user.id)
            # 执行管道命令
            # p1.execute()
            cart = {}
            for sku_id, count in redis_cart.items():
                if sku_id in redis_selected:
                    selected = True
                else:
                    selected = False
                cart[int(sku_id)] = {
                    'count': count,
                    'selected': selected
                }


        # 3.未登录用户cookie查询
        else:
            cart_str = requset.COOKIES.get('cart')
            if cart_str is not None:
                cart_bytes = base64.b64decode(cart_str)
                cart = pickle.loads(cart_bytes)
            else:
                cart = {}
        # 4.查询商品对象,并查询到商品的count和selected
        skus = SKU.objects.filter(id__in=cart)
        for sku in skus:
            sku.count = cart[sku.id]['count']
            sku.selected = cart[sku.id]['selected']
        # 5.将商品信息序列化,返回
        serializer = CartSKUSerializer(skus, many=True)
        return Response(serializer.data)

    """修改购物车数据"""

    def put(self, request):
        """
        1.创建序列化器,校验数据
        2.校验用户是否登陆
        3.登陆修改redis数据
        4.未登录修改cookie
        5.返回响应
        """

        # 1.创建序列化器,校验数据
        serializer = CartSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        sku_id = serializer.data.get('sku_id')
        count = serializer.data.get('count')
        selected = serializer.data.get('selected')
        # 2.校验用户是否登陆
        try:
            user = request.user
        except Exception:
            user = None
        # 3.登陆修改redis数据
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('cart')
            p1 = redis_conn.pipeline()
            p1.hset('cart_%s' % user.id, sku_id, count)
            if selected:
                p1.sadd('cart_selected_%s' % user.id, sku_id)
            else:
                p1.srem('cart_selected_%s' % user.id, sku_id)
            p1.execute()
            return Response(serializer.data)
        # 4.未登录修改cookie
        else:
            cart_str = request.COOKIES.get('cart')
            if cart_str is not None:
                cart_bytes = base64.b64decode(cart_str)
                cart = pickle.loads(cart_bytes)
            else:
                cart = {}
            cart[sku_id] = {
                'count': count,
                'selected': selected
            }

            cart_bytes = pickle.dumps(cart)
            cart_cookie = base64.b64encode(cart_bytes)
            response = Response(serializer.data)
            response.set_cookie('cart', cart_cookie)
            # 5.返回响应
            return response

    """删除购物车数据"""

    def delete(self, request):
        """
        1.创建序列化器进行校验
        2.获取校验过的数据
        3.判断用户是否登陆
        4.登陆对redis数据进行删除
        5.未登录对cookie数据进行删除
        6.返回响应
        """
        # 1.创建序列化器进行校验
        serializer = CartDeleteSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 2.获取校验过的数据
        sku_id = serializer.data.get('sku_id')
        # 3.判断用户是否登陆
        try:
            user = request.user
        except:
            user = None
        # 4.登陆对redis数据进行删除
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('cart')
            p1 = redis_conn.pipeline()
            p1.hdel('cart_%s' % user.id, sku_id)
            p1.srem('cart_selected_%s' % user.id, sku_id)
            return Response(status=status.HTTP_204_NO_CONTENT)
        # 5.未登录对cookie数据进行删除
        else:
            cart_str = request.COOKIES.get('cart')
            if cart_str is not None:

                cart_bytes = base64.b64decode(cart_str)
                cart = pickle.loads(cart_bytes)
            else:
                cart = {}
            # 删除数据
            if sku_id in cart:
                del cart[sku_id]
            # 组织cookie数据
            cart_bytes = pickle.dumps(cart)
            cart_cookie = base64.b64encode(cart_bytes).decode()
            response = Response(serializer.data)
            response.set_cookie('cart',cart_cookie)
            # 6.返回响应
            return response
